<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <style>
    .item {
      height: 500px;
      width: 50%;
      border-radius: 16px;
      background-color: aquamarine;
      display: flex;
      justify-content: center;
      align-items: center;
      box-shadow: rgba(17, 12, 46, 0.15) 0px 48px 100px 0px;
      font-size: 4rem;
      color: #fff;
      background-image: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
    }

    .container {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 64px;
      margin: 0 auto;
      padding: 32px;
    }
  </style>
</head>

<body>
  <div id="app" class="container">
    <div class="item" v-slide-in v-for="item in list" :key="item">{{item}}</div>
  </div>

  <script>
    const { createApp, ref } = Vue
    const DISTANCE = 50;
    const aniMap = new WeakMap();
    const ob = new IntersectionObserver((entries) => {
      for (const entry of entries) {
        if (entry.isIntersecting) {
          console.log('出现了', entry.target.innerText)
          const ani = aniMap.get(entry.target)
          if (ani) {
            ani.play();
            ob.unobserve(entry.target)
          }
        }
      }
    })

    function isBeforeViewPort(el) {
      const rect = el.getBoundingClientRect();
      return rect.top - DISTANCE > window.innerHeight;
    }


    const app = createApp({
      setup() {
        const message = ref('Hello vue!')
        return {
          list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
        }
      },
      directives: {
        slideIn: {
          mounted(el) {
            if (!isBeforeViewPort(el)) {
              return;
            }
            const animation = el.animate([
              {
                transform: `translateY(${DISTANCE}px)`,
                opacity: 0.5,
              },
              {
                transform: `translateY(0)`,
                opacity: 1,
              }
            ], {
              duration: 500,
              easing: 'ease-in-out',
              fill: 'forwards'
            })

            animation.pause();
            ob.observe(el)
            aniMap.set(el, animation)
          },

          unmounted(el) {
            ob.unobserve(el);
          }

        }
      }
    })

    // app.directive('slide-in', {})


    app.mount('#app')
  </script>
</body>

</html>